﻿#region FileHeader
//////////////////////////////////////////////////////////////////////////////////
// Author:                          Hector Llanos
// Date:                            08.27.2010
// FileName:                        CEventSystem.cs
// Reason:                          system that controls all the events in the game
//////////////////////////////////////////////////////////////////////////////////
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Event_System
{
    using EVENTID = System.String;

    public class CEventSystem
    {
        //	Our Database, this will contain clients that can "listen" for events.
        private Dictionary<EVENTID, IListener> m_ClientDatabase;

        private static CEventSystem m_pInstance = new CEventSystem();

        //	Events waiting to be processed.
        Queue<CEvent> m_lCurrentEvents;

        CEventSystem()
        {
            m_ClientDatabase = new Dictionary<EVENTID, IListener>();
            m_lCurrentEvents = new Queue<CEvent>();
        }
        private void DispatchEvent(CEvent pEvent)
        {

            foreach (KeyValuePair<EVENTID, IListener> pair in m_ClientDatabase)
            {
                pair.Value.HandleEvent(pEvent);
            }
        }
        private bool AlreadyRegistered(EVENTID eventID, IListener pClient)
        {

            foreach (KeyValuePair<EVENTID, IListener> pair in m_ClientDatabase)
            {
                if (pair.Value == pClient)
                    return true;
            }
            return false;
        }

        public static CEventSystem Instance
        {
            get { return CEventSystem.m_pInstance; }
        }
        
        //	This adds a client to the database.  This will make new "buckets" if necessary and then
		//	add the client to that given bucket.
        public void RegisterClient(EVENTID eventID, IListener pClient)
        {
            //	Error check to make sure the client exists and hasn't been 
            //  registered for this event already.
            if (pClient == null || AlreadyRegistered(eventID, pClient))
                return;

            //	Register (Build) the database of clients.
            m_ClientDatabase.Add(eventID, pClient);
        }
        
		//	Unregisters the client for the specified event only
        public void UnregisterClient(EVENTID eventID, IListener pClient)
        {
            //	Make an iterator that will iterate all of our clients that
            //	should be receiving this event
            if (m_ClientDatabase.ContainsKey(eventID))
            {
                m_ClientDatabase.Remove(eventID);
            }

        }

		//	Removes the client from the database entirely
        public void UnregisterClientAll(IListener pClient)
        {
            foreach (KeyValuePair<EVENTID, IListener> pEvent in m_ClientDatabase)
            {
                m_ClientDatabase.Remove(pEvent.Key);
            }
        }
       
		//	Sends an event to be processed later on.
        public void SendEvent(EVENTID eventID, object pData)
        {
            m_lCurrentEvents.Enqueue(new CEvent(eventID, pData));
        }

		//	Processes all events in our event list.
        public void ProcessEvents( )
        {
            while (m_lCurrentEvents.Count > 0)
            {
                DispatchEvent(m_lCurrentEvents.Peek());
                m_lCurrentEvents.Dequeue();
            }
        }

		//	Clears all pending events
        public void ClearEvents( )
        {
            m_lCurrentEvents.Clear();
        }

		//	Unregisters all objects
        public void ShutdownEventSystem( )
        {
            m_ClientDatabase.Clear();
        }
    }
}
